package cn.stylefeng.guns.modular.api.controller;

import cn.stylefeng.guns.base.auth.jwt.JwtTokenUtil;
import cn.stylefeng.guns.base.auth.jwt.payload.JwtPayLoad;
import cn.stylefeng.guns.base.consts.ConstantsContext;
import cn.stylefeng.guns.core.SmsService;
import cn.stylefeng.guns.modular.api.request.LoginRequest;
import cn.stylefeng.guns.modular.rms.entity.Company;
import cn.stylefeng.guns.modular.rms.service.CompanyService;
import cn.stylefeng.guns.modular.ums.entity.Member;
import cn.stylefeng.guns.modular.ums.model.params.MemberParam;
import cn.stylefeng.guns.modular.ums.model.params.RecommendIncomeRecordsParam;
import cn.stylefeng.guns.modular.ums.model.params.WxPhoneInfo;
import cn.stylefeng.guns.modular.ums.model.result.MemberResult;
import cn.stylefeng.guns.modular.ums.model.result.RecommendIncomeRecordsResult;
import cn.stylefeng.guns.modular.ums.service.MemberService;
import cn.stylefeng.guns.modular.ums.service.RecommendIncomeRecordsService;
import cn.stylefeng.guns.modular.wms.model.params.ResumeParam;
import cn.stylefeng.guns.modular.wms.model.result.ResumeResult;
import cn.stylefeng.guns.modular.wms.service.ResumeService;
import cn.stylefeng.guns.sys.core.util.SaltUtil;
import cn.stylefeng.guns.utils.AES;
import cn.stylefeng.guns.utils.Constant;
import cn.stylefeng.guns.utils.MemberTokenUtil;
import cn.stylefeng.guns.utils.StringUtil;
import cn.stylefeng.guns.utils.redis.RedisCache;
import cn.stylefeng.roses.core.base.controller.BaseController;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.RequestEmptyException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 〈一句话功能简述〉<br>
 * 〈会员相关对外接口〉
 *
 * @author muconan
 * @create 2019/12/24
 * @since 1.0.0
 */
@Controller
@RequestMapping("/api/ums")
@Api(tags = "会员相关对外接口")
@CrossOrigin
public class ApiUmsController extends BaseController {

    @Resource
    private MemberService memberService;

    @Resource
    private SmsService smsService;

    @Resource
    private ResumeService resumeService;

    @Autowired
    private RedisCache redisCache;

    @Resource
    private CompanyService companyService;


    /**
     * 会员注册接口
     *
     * @param phone
     * @param password
     * @param code
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/register", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "会员注册", notes = "会员注册处理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String", paramType = "query")
    })
    public ResponseData register(String phone, String password, String code) throws Exception {
        if (StringUtils.isEmpty(phone)) {
            return ResponseData.error("手机号不能为空");
        }
        if (StringUtils.isEmpty(code)) {
            return ResponseData.error("验证码不能为空");
        }
        //校验验证码是否正确，模拟直接注释掉
        boolean verify = smsService.verifyCode(phone, code);
        if (verify == false) {
            return ResponseData.error("验证码错误或失效！");
        }

        //判断用户是否存在，如果不存在则自动注册
        MemberParam memberParam = new MemberParam();
        memberParam.setPhone(phone);
        memberParam.setPassword(password);
        memberParam.setCode(StringUtil.toSerialCode(memberService.count()));
//        memberParam.setRemark(inviteCode);//临时存放推广码
        memberParam.setNickName(phone);
        Member curr_member = memberService.add(memberParam);

        Map<String, Object> data = new HashMap<>();
        JwtPayLoad payLoad = new JwtPayLoad(curr_member.getMemberId().longValue(), curr_member.getPhone(), ConstantsContext.getJwtSecret());
        //创建Token信息
        String token = JwtTokenUtil.generateToken(payLoad);

        data.put("token", token);
        data.put("memberId", curr_member.getMemberId().toString());
        return ResponseData.success(data);
    }


    /**
     * 获取验证码
     *
     * @param phone
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getVerifyCode", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "获取验证码", notes = "获取验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String", paramType = "query")
    })
    public ResponseData getVerifyCode(String phone) {
        return ResponseData.success();//模拟直接返回成功
//        String code = RandomStringUtils.randomNumeric(6);
//        boolean smsResult = smsService.sendSmsCode(phone, code);
//        if (smsResult){
//            //短信验证码缓存15分钟，
//            redisCache.setCacheObject(getCacheKey(phone), code);
//            redisCache.expire(getCacheKey(phone), 15 * 60);
//            return ResponseData.success();
//        }else{
//            return ResponseData.error("验证码获取失败");
//        }
    }

    /**
     * 会员密码登陆
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/memberLogin", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "会员密码登陆", notes = "会员密码登陆")
    public ResponseData memberLogin(LoginRequest request) {
        if (ToolUtil.isOneEmpty(request.getPhone(), request.getPassword())) {
            return ResponseData.error("账号或密码为空！");
        }
        try {
            String code = "NO_CODE";
            MemberResult memberResult = memberService.getMemberForLogin(request.getPhone(), request.getPassword(), code);
            Map<String, Object> data = new HashMap<>();
            if (memberResult != null) {
                JwtPayLoad payLoad = new JwtPayLoad(memberResult.getMemberId().longValue(), memberResult.getPhone(), ConstantsContext.getJwtSecret());
                //创建Token信息
                String token = JwtTokenUtil.generateToken(payLoad);
                //失效时间
                String expire = String.valueOf(JwtTokenUtil.getExpirationDateFromToken(token).getTime());
                data.put("token", token);
                data.put("currMember", memberResult);
                data.put("expire", expire);
            } else {
                return ResponseData.error("会员登陆失败,请检查填写是否正确！");
            }
            return ResponseData.success(data);
        } catch (Exception e) {
            return ResponseData.error(e.getMessage());
        }
    }

    /***
     * 手机验证码登陆
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/memberLoginForCode", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "手机验证码登陆", notes = "手机验证码登陆")
    public ResponseData memberLoginForCode(LoginRequest request) {

        if (ToolUtil.isOneEmpty(request.getPhone())) {
            return ResponseData.error("账号或密码为空！");
        }

        if (ToolUtil.isOneEmpty(request.getCode())) {
            return ResponseData.error("验证码不能为空！");
        }

        //校验验证码是否正确，模拟直接注释掉
//        boolean verify=smsService.verifyCode(request.getPhone(),request.getCode());
//        if (verify==false){
//            return  ResponseData.error("验证码错误或失效！");
//        }
        String password = null;
        MemberResult memberResult = memberService.getMemberForLogin(request.getPhone(), password, request.getCode());

        Map<String, Object> data = new HashMap<>();
        if (ToolUtil.isEmpty(memberResult)) {
            return ResponseData.error("登陆失败,请检查填写是否正确！");
        } else {
            JwtPayLoad payLoad = new JwtPayLoad(memberResult.getMemberId().longValue(),
                    memberResult.getPhone(), ConstantsContext.getJwtSecret());
            //创建Token信息
            String token = JwtTokenUtil.generateToken(payLoad);
            //失效时间
            String expire = String.valueOf(JwtTokenUtil.getExpirationDateFromToken(token).getTime());
            data.put("token", token);
            data.put("currMember", memberResult);
            data.put("expire", expire);
        }
        return ResponseData.success(data);
    }


    /**
     * 取得会员信息
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getMember", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "会员信息", notes = "根据Token取得会员信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "header")
    })
    public ResponseData getMember() {
        //取得当前Token登录者会员的ID
        int memberId = MemberTokenUtil.getMemberId();
        MemberParam memberParam = new MemberParam();
        memberParam.setMemberId(memberId);
        MemberResult memberResult = memberService.getMember(memberParam);
        if (memberResult == null) {
            return ResponseData.success(null);
        }
        //如果企业，获取企业认证信息
        if (memberResult.getMemberRole() == 1 && memberResult.getCompanyId() > 0) {
            Company company = companyService.getById(memberResult.getCompanyId());
            memberResult.setCompanyAuth(company.getVerifyStatus());
        }
        //如果是个人，查询简历
        if (memberResult.getMemberRole() == 0) {
            ResumeResult resumeResult = resumeService.findBySpec(new ResumeParam().setMemberId(memberId));
            if (resumeResult != null) {
                memberResult.setIfAddResume(true);
            } else {
                memberResult.setIfAddResume(false);
            }
        }
        return ResponseData.success(memberResult);
    }

    /**
     * 根据用户ID取得会员信息
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getMemberById", method = {RequestMethod.GET})
    @ApiOperation(value = "根据会员ID取得会员信息", notes = "根据会员ID取得会员信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token", paramType = "header"),
            @ApiImplicitParam(name = "memberId", value = "会员ID", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "isLogin", value = "是否登录（1-登录，其他表示未登录）", dataType = "Integer", paramType = "query"),
    })
    public ResponseData getMemberById(Integer memberId, Integer isLogin) {
        MemberParam memberParam = new MemberParam();
        memberParam.setMemberId(memberId);
        MemberResult member = memberService.getMember(memberParam);
        return ResponseData.success(member);
    }


    /**
     * 根据用户Sn取得会员信息
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getMemberBySn", method = {RequestMethod.GET})
    @ApiOperation(value = "根据用户Sn取得会员信息", notes = "根据用户Sn取得会员信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "memberSn", value = "会员SN", dataType = "String", paramType = "query")
    })
    public ResponseData getMemberBySn(String memberSn) {
        MemberParam memberParam = new MemberParam();
        memberParam.setMemberSn(memberSn);
        MemberResult member = memberService.getMember(memberParam);
        return ResponseData.success(member);
    }

    /**
     * 更新会员信息
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/updateMemberInfo", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "更新会员信息", notes = "更新会员信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "header")
    })
    public ResponseData updateMemberInfo(MemberParam param) {
        //取得当前Token登录者会员的ID
        int memberId = MemberTokenUtil.getMemberId();
        param.setMemberId(memberId);
        memberService.update(param);
        return ResponseData.success();
    }


    /**
     * 忘记密码
     *
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/resetPwd", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "忘记密码", notes = "忘记密码")
    public ResponseData resetPwd(LoginRequest request) throws Exception {
        if (StringUtils.isEmpty(request.getPhone())) {
            return ResponseData.error("手机号不能为空");
        }
        if (StringUtils.isEmpty(request.getCode())) {
            return ResponseData.error("验证码不能为空");
        }
//        boolean verify=smsService.verifyCode(request.getPhone(),request.getCode());
//        if (verify==false){
//            return  ResponseData.error("验证码错误或失效！");
//        }
        //判断用户是否存在，如果不存在则自动注册
        MemberParam memberParam = new MemberParam();
        memberParam.setPhone(request.getPhone());
        MemberResult memberResult = memberService.getMember(memberParam);
        if (memberResult == null) {
            return ResponseData.error("用户不存在");
        }
        String salt = SaltUtil.getRandomSalt();
        String t_pass = SaltUtil.md5Encrypt(request.getPassword(), salt);
        memberResult.setPassword(t_pass);
        memberResult.setSalt(salt);
        MemberParam entity = new MemberParam();
        ToolUtil.copyProperties(memberResult, entity);
        memberService.update(entity);
        return ResponseData.success();
    }

    /**
     * 修改登录密码
     *
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/updatePwd", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "修改登录密码", notes = "修改登录密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "header"),
    })
    public ResponseData updatePwd(@RequestBody LoginRequest request) throws Exception {
        //取得当前Token登录者会员的ID
        int memberId = MemberTokenUtil.getMemberId();
        if (StringUtils.isEmpty(request.getCode())) {
            return ResponseData.error("验证码不能为空");
        }
        if (StringUtils.isEmpty(request.getPassword())) {
            return ResponseData.error("密码不能为空");
        }
        //判断用户是否存在，如果不存在则自动注册
        MemberParam memberParam = new MemberParam();
        memberParam.setMemberId(memberId);
        MemberResult memberResult = memberService.getMember(memberParam);
        if (memberResult == null) {
            return ResponseData.error("用户不存在");
        }
        String salt = SaltUtil.getRandomSalt();
        String t_pass = SaltUtil.md5Encrypt(request.getPassword(), salt);
        memberResult.setPassword(t_pass);
        memberResult.setSalt(salt);
        MemberParam entity = new MemberParam();
        ToolUtil.copyProperties(memberResult, entity);
        memberService.update(entity);
        return ResponseData.success();
    }


    @ResponseBody
    @RequestMapping(value = "/getOpenId", method = {RequestMethod.GET})
    @ApiOperation(value = "小程序获取OpenId", notes = "小程序获取OpenId")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "code", dataType = "String", paramType = "query"),
    })
    public ResponseData getOpenId(String code) {
        System.out.println(code);
        String appid = "wx9f34994e4de784fb";
        String appsecret = "15b8e21aa0d57a770d745df368d861d8";
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + appsecret + "&js_code=" + code + "&grant_type=authorization_code";
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        try {
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String responseContent = EntityUtils.toString(entity, "UTF-8");
            System.out.println(responseContent + "响应报文");
            Map<String, String> res = new HashMap<>();
            Gson gson = new Gson();
            res = gson.fromJson(responseContent, res.getClass());
            String openid = res.get("openid");
            String session_key = res.get("session_key");
            System.out.println(res);
            System.out.println(openid + "获取到了openid");
            Map<String, Object> map = new HashMap<>();
            map.put("openId", openid);
            map.put("session_key", session_key);
            return ResponseData.success(map);
        } catch (Exception e) {
            System.out.println("请求错误");
            return ResponseData.error(e.getMessage());
        }
    }


    /**
     * 小程序绑定手机号
     *
     * @return
     */
    @RequestMapping("bindPhoneForWx")
    @ResponseBody
    public synchronized ResponseData bindPhoneForWx(String openid, String keyStr, String ivStr, String encDataStr, String avatar, String nickName) {
        Map<String, Object> map = new HashMap<>();
        //解析手机号
        WxPhoneInfo wxPhoneInfo = null;
        System.err.println("encDataStr=" + encDataStr + ",keyStr=" + keyStr + ",ivStr=" + ivStr);
        try {
            String result = AES.wxDecrypt(encDataStr, keyStr, ivStr);
            Gson gson = new Gson();
            wxPhoneInfo = gson.fromJson(result, WxPhoneInfo.class);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseData.error("绑定手机号异常");
        }
        if (wxPhoneInfo == null) {
            return ResponseData.error("绑定手机号异常");
        }
        //更新手机号
        MemberParam user = new MemberParam();
//        user.setOpenid(openid);
        user.setPhone(wxPhoneInfo.getPhoneNumber().trim());
        MemberResult u = memberService.getMember(user);
        if (u == null) {
            user.setCreateTime(new Date());
            user.setLoginTime(new Date());
            user.setOpenId(openid);
            user.setNickName(nickName);
            user.setName(nickName);
            user.setAvatar(avatar);
            user.setMemberSn(StringUtil.getOutTradeNo());
            memberService.add(user);
            u = memberService.getMemberByOpenId(openid);
        } else {
            user.setMemberId(u.getMemberId());
            user.setOpenId(openid);
            user.setNickName(nickName);
            user.setName(nickName);
            user.setAvatar(avatar);
            user.setLoginTime(new Date());
            memberService.update(user);
        }
        JwtPayLoad payLoad = new JwtPayLoad(u.getMemberId().longValue(),
                u.getPhone(), ConstantsContext.getJwtSecret());
        //创建Token信息
        String token = JwtTokenUtil.generateToken(payLoad);
        //失效时间
        String expire = String.valueOf(JwtTokenUtil.getExpirationDateFromToken(token).getTime());
        map.put("token", token);
        map.put("currMember", u);
        map.put("expire", expire);
        return ResponseData.success(map);
    }

    /**
     * 小程序授权登录方法
     *
     * @return
     */
    @RequestMapping(value = "xcxUserLogin", method = {RequestMethod.GET})
    @ApiOperation(value = "小程序授权登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "openid", value = "openid", dataType = "String", paramType = "query"),
    })
    @ResponseBody
    public synchronized ResponseData xcxUserLogin(String openid, String avatar, String nickName) {
        System.out.println("openid=" + openid);
        MemberResult u = memberService.getMemberByOpenId(openid);
        Map<String, Object> map = new HashMap<>();
        if (u == null) {
            return ResponseData.success("账号不存在");
        } else if (u.getPhone() == null) {
            return ResponseData.success("未绑定手机号");
        } else {
            memberService.update(new MemberParam().setMemberId(u.getMemberId()).setLoginTime(new Date()));
            JwtPayLoad payLoad = new JwtPayLoad(u.getMemberId().longValue(),
                    u.getPhone(), ConstantsContext.getJwtSecret());
            //创建Token信息
            String token = JwtTokenUtil.generateToken(payLoad);
            //失效时间
            String expire = String.valueOf(JwtTokenUtil.getExpirationDateFromToken(token).getTime());
            map.put("token", token);
            map.put("currMember", u);
            map.put("expire", expire);
        }
        return ResponseData.success(map);
    }


    /**
     * 角色切换
     */
    @ResponseBody
    @RequestMapping(value = "/switchRole", method = {RequestMethod.GET})
    @ApiOperation(value = "角色切换", notes = "角色切换")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "header"),
            @ApiImplicitParam(name = "role", value = "角色（0-求职，1-招聘）", required = true, dataType = "Integer", paramType = "query"),
    })
    public ResponseData switchRole(Integer role) throws Exception {
        //判断角色是否存在
        int memberId = MemberTokenUtil.getMemberId();
        Member member = memberService.getById(memberId);
        Map<String, Object> map = new HashMap<>();
        //切换到用户，查询是否存在简历
        boolean result = false;
        if (role == 0) {
            ResumeParam resumeParam = new ResumeParam();
            resumeParam.setMemberId(memberId);
            ResumeResult resumeResult = resumeService.findBySpec(resumeParam);
            if (resumeResult != null) {
                //直接切换
                result = true;
            } else {
                //简历不存在
                result = false;
            }
        } else if (role == 1) {
            if (member.getCompanyId() > 0) {
                //直接切换
                result = true;
            } else {
                //未绑定公司
                result = false;
            }
        }
        map.put("result", result);
        //切换角色
        member.setMemberRole(role);
        memberService.updateById(member);
        return ResponseData.success(map);
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return Constant.SMS_KEY + configKey;
    }

}